package it.sd.wdc.spider.executer;

import it.sd.utility.XMLWrapper;
import it.sd.wdc.spider.bean.PostParameters;
import it.sd.wdc.spider.executer.parser.SpiderParser;
import it.sd.wdc.spider.repository.WDCParams;
import it.sd.wdc.spider.repository.WDCStep;
import it.sd.wdc.spider.repository.WDCStepResult;
import it.sd.wdc.spider.repository.template.SpiderNodeTemplate;

import java.util.Iterator;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;

public class StepExecuter {

	Logger logger = Logger.getLogger(this.getClass());
	
	WDCStep step = null;
	
	/**
	 * inizializzazione dello step con configurazione step e configurazione pagina
	 * @param step
	 * @param page
	 */
	public StepExecuter(WDCStep step) {
		this.step = step;
	}

	public String toString() {
		return step.getHost() + step.getAction();
	}
	
	/**
	 * esegue lo step prelevando e riportando i parametri nella sessione
	 * @param session
	 * @return
	 */
	public String execute(ScriptSession session, SpiderNodeTemplate template) throws Exception{
		
		// richiede la pagina
		String htmlpage = getPage(session);

		// parserizza la pagina trasformando l'hml nell'xml definito dal template <nomepagina>.xml
		SpiderParser sp = new SpiderParser(template, htmlpage);
		Document doc = sp.parse();
		XMLWrapper w = new XMLWrapper(doc);
		
		logger.debug("output: " + w);
		session.addPage(w);
	
		addOutput(session.getAttributes(), w);
		
		// a questo punto determino se c'� uno step successivo
		return determinaStepSuccessivo(w, session);
		
	}
	
	private void addOutput(XMLWrapper sessionAttribute , XMLWrapper xmlInput) throws Exception {

    	// recupero parametri di input
    	for (Iterator<WDCParams> iterator = step.iterateOutputParams(); iterator.hasNext();) {
    		WDCParams output = iterator.next();
    		String value = output.getValue();
    		if (value.startsWith("${")) {
    			value = xmlInput.extractStringValue(value);
    		}
    		sessionAttribute.setValue(output.getName(), value);
    	}
    	
    }

	public String getPage(ScriptSession session) throws Exception{
		
		// prepara action
		String action= step.getAction();
		int pos = action.indexOf("${");
		if (pos > -1 ) {
			String value = action.substring(pos, action.indexOf("}")+1);
			value = session.getAttributes().extractStringValue(value);
			action = action.substring(0, pos) + value + action.substring(action.indexOf("}")+1);
		}
		// prepara host
		String host= step.getHost();
		pos= host.indexOf("${");
		if (pos > -1 ) {
			String value = host.substring(pos, host.indexOf("}")+1);
			value = session.getAttributes().extractStringValue(value);
			host = host.substring(0, pos) + value + host.substring(host.indexOf("}")+1);
		}

		// prepara lista parametri
		PostParameters pp = new PostParameters();
		for (Iterator<WDCParams> iterator = step.iterateInputParams(); iterator.hasNext();) {
			WDCParams parm = iterator.next();
			String value = parm.getValue();
			if (value.startsWith("${")) {
				value = session.getAttributes().extractStringValue(value);
			}
			pp.addParameter(parm.getName(), value);
		}
		
		// richiede la pagina
		return session.getPage(host,
							   action,
							   step.getMethod(),
							   pp);
		
	}

	private String determinaStepSuccessivo(XMLWrapper w, ScriptSession session) throws Exception {
		
		String stepSuccessivo = null;

		for(Iterator<WDCStepResult> it = step.iterateStepResults(); it.hasNext();) {
			boolean execute = true;
			WDCStepResult res = it.next();
			String condition = (res.getCondition());

			int pos = condition.indexOf("${");
			while (pos > -1 ) {
				String value = condition.substring(pos, condition.indexOf("}")+1);
				value = session.getAttributes().extractStringValue(value);
				condition = condition.substring(0, pos) + value + condition.substring(condition.indexOf("}")+1);
				pos = condition.indexOf("${");
			}

			if (condition !=null) {
				if (!w.extractBooleanValue(condition)) {
					execute = false;
				}
			}
			if (execute) {
				stepSuccessivo = res.getNextStep();
				break;
			}
		}
		
		return stepSuccessivo;
	}
}
